# 透视变换工具
import numpy as np
import cv2

# def order_points_new(pts):
#     xSorted = pts[np.argsort(pts[:, 0]), :]
#     leftMost = xSorted[:2, :]
#     rightMost = xSorted[2:, :]
#
#     if leftMost[0, 1] != leftMost[1, 1]:
#         leftMost = leftMost[np.argsort(leftMost[:, 1]), :]
#     else:
#         leftMost = leftMost[np.argsort(leftMost[:, 0])[::-1], :]
#
#     (tl, bl) = leftMost
#     if rightMost[0, 1] != rightMost[1, 1]:
#         rightMost = rightMost[np.argsort(rightMost[:, 1]), :]
#     else:
#         rightMost = rightMost[np.argsort(rightMost[:, 0])[::-1], :]
#     (tr, br) = rightMost
#
#     return np.array([tl, tr, br, bl], dtype="float32")


def order_points_simple(pts):
    # 对点进行排序：左上、右上、右下、左下
    rect = np.zeros((4, 2), dtype="float32")

    # 计算每个点的和与差
    s = pts.sum(axis=1)
    diff = np.diff(pts, axis=1)

    rect[0] = pts[np.argmin(s)]  # 左上角（和最小）
    rect[2] = pts[np.argmax(s)]  # 右下角（和最大）
    rect[1] = pts[np.argmin(diff)]  # 右上角（差最小）
    rect[3] = pts[np.argmax(diff)]  # 左下角（差最大）

    return rect

# def four_point_transform(image, pts):
#     # rect = order_points_new(pts)
#     rect = order_points_simple(pts)
#     (tl, tr, br, bl) = rect
#
#     widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
#     widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
#     maxWidth = max(int(widthA), int(widthB))
#
#     heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
#     heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
#     maxHeight = max(int(heightA), int(heightB))
#
#     dst = np.array([
#         [0, 0],
#         [maxWidth - 1, 0],
#         [maxWidth - 1, maxHeight - 1],
#         [0, maxHeight - 1]], dtype="float32")
#
#     M = cv2.getPerspectiveTransform(rect, dst)
#     warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
#     return warped


def four_point_transform(image, pts):
    rect = order_points_simple(pts)
    (tl, tr, br, bl) = rect

    # 计算宽度和高度
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))

    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))

    # 增加边界扩展（比如增加10%的边界）
    expand_ratio = 0.05  # 5%的边界扩展
    expand_x = int(maxWidth * expand_ratio)
    expand_y = int(maxHeight * expand_ratio)

    maxWidth += 2 * expand_x
    maxHeight += 2 * expand_y

    # 调整目标坐标，留出边界
    dst = np.array([
        [expand_x, expand_y],
        [maxWidth - expand_x - 1, expand_y],
        [maxWidth - expand_x - 1, maxHeight - expand_y - 1],
        [expand_x, maxHeight - expand_y - 1]], dtype="float32")

    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    return warped